/**
 * 绘图类: 绘制各种图形
 * 
 * @namespace Note.Painter
 * 
 * 构造函数
 * 
 * @constructor Painter
 * @author JunEnstein 2017-05-18
 * @param object context 绘图句柄对象
 * @param CacheLayer cacheLayer 缓存对象
 */
Note.Painter = function(context, cacheLayer){
	/**
	 * 绘图句柄
	 * @type {Object}
	 */
	this._context = context;
	/**
	 * 缓存对象
	 * @type {Object}
	 */
	this._cache = cacheLayer;
	/**
	 * 橡皮样式
	 * @type {Object}
	 */
	this._eraserStyle = {
		size: 5,
		lineWidth: 1,
		lineCap: "round",
		strokeStyle: "gray",
		fillStyle: "gray"
	};
	/**
	 * 默认画笔样式
	 * 详细画笔样式,请参考http://www.runoob.com/tags/ref-canvas.html
	 * @type {Object}
	 */
	this._defaultStyle = {
		/**
		 * 线条宽度
		 * @type {Number}
		 */
		lineWidth: 3,
		/**
		 * 线段端点样式.
		 * 	butt   向线条的每个末端添加平直的边缘
		 * 	round  向线条的每个末端添加圆形线帽
		 * 	square 向线条的每个末端添加正方形线帽
		 * 	注意："round" 和 "square" 值会使线条略微变长
		 * @type {String}
		 */
		lineCap: "round",
		/**
		 * 线段拐点样式
		 * 当两条线交汇时,设置或返回所创建边角的类型
		 * bevel	创建斜角
		 * round	创建圆角
		 * miter	创建尖角
		 * @type {String}
		 */
		lineJoin: "round",
		/**
		 * 笔触的颜色、渐变或模式
		 * color	指示绘图笔触颜色的 CSS 颜色值。默认值是 #000000
		 * gradient	用于填充绘图的渐变对象(线性 或 放射性)
		 * pattern	用于创建 pattern 笔触的 pattern 对象
		 * @type {color|gradient|pattern}
		 */
		strokeStyle: "black",
		/**
		 * 填充绘画的颜色、渐变或模式
		 * 具体用法与strokeStyle相同
		 * @type {color|gradient|pattern}
		 */
		fillStyle: "black",
		/**
		 * 阴影的颜色
		 * @type {color}
		 */
		shadowColor: "#000000",
		/**
		 * 阴影的模糊级数
		 * @type {Number}
		 */
		shadowBlur : 0,
		/**
		 * 阴影与形状的水平距离
		 * @type {Number}
		 */
		shadowOffsetX: 0,
		/**
		 * 阴影与形状的垂直距离
		 * @type {Number}
		 */
		shadowOffsetY: 0
	};
	
	// 应用画笔样式
	this.setStyles(this._defaultStyle);
};

/**
 * 设置画笔样式
 * @method setStyle
 * @author JunEnstein 2017-05-19
 * @param  {Object} style 画笔样式
 */
Note.Painter.prototype.setStyles = function(styles){
	for(var key in styles){
		this._context[key] = styles[key];
	}
};

/**
 * 设置橡皮样式
 * @method setEraserStyle
 * @author JunEnstein 2017-05-21
 * @param  {Object} styles 橡皮样式
 */
Note.Painter.prototype.setEraserStyle = function(styles){
	for(var key in styles){
		this._eraserStyle[key] = styles[key];
	}
};

/**
 * 绘制一条直线
 * @method drawLine
 * @author JunEnstein 2017-05-19
 * @param  Array paths 图形轨迹
 */
Note.Painter.prototype.drawLine = function(paths){
	if(paths.length == 0) return ;
	var start = paths[0];
	var end = paths[paths.length-1];
	this._context.beginPath();
	this._context.moveTo(start.x, start.y);
	this._context.lineTo(end.x, end.y);
	this._context.stroke();
};

/**
 * 绘制一条曲线
 * @method drawCurve
 * @author JunEnstein 2017-05-19
 * @param  Array paths 图形轨迹
 */
Note.Painter.prototype.drawCurve = function(paths){
	if(paths.length == 0) return ;
	this._context.beginPath();
	this._context.moveTo(paths[0].x, paths[0].y);
	for(var i = 1; i < paths.length; i++){
		this._context.lineTo(paths[i].x, paths[i].y);
	}
	this._context.stroke();
};

/**
 * 绘制一个矩形
 * @method drawRectangle
 * @author JunEnstein 2017-05-19
 * @param  Array paths 图形轨迹
 */
Note.Painter.prototype.drawRectangle = function(paths){
	if(paths.length == 0) return ;
	var start = paths[0];
	var end = paths[paths.length-1];
	var width = Math.abs(start.x - end.x);
	var height = Math.abs(start.y - end.y);
	var sx = Math.min(start.x, end.x);
	var sy = Math.min(start.y, end.y);
	this._context.strokeRect(sx, sy, width, height);
};

/**
 * 绘制一个椭圆
 * @method drawEllipse
 * @author JunEnstein 2017-05-19
 * @param  Array paths 图形轨迹
 */
Note.Painter.prototype.drawEllipse = function(paths){
	if(paths.length == 0) return ;
	var start = paths[0];
	var end = paths[paths.length-1];
	var cx = (start.x + end.x)/2.0;
	var cy = (start.y + end.y)/2.0;
	var a = Math.abs(start.x - end.x) / 2.0;
	var b = Math.abs(start.y - end.y) / 2.0;
	var step = (a > b) ? 1.0 / a : 1.0 / b;
	this._context.beginPath();
	this._context.moveTo(cx + a, cy);
	for(var i = 0; i < 2 * Math.PI; i += step) {
		this._context.lineTo(cx + a * Math.cos(i), cy + b * Math.sin(i));
	}
	this._context.closePath();
	this._context.stroke();
};

/**
 * 绘制一个橡皮擦
 * @method drawEllipse
 * @author JunEnstein 2017-05-19
 * @param  Array paths 图形轨迹
 */
Note.Painter.prototype.drawEraser = function(paths){
	if(paths.length == 0) return ;
	// 保存之前的画笔样式
	this._context.save();
	// 设置橡皮样式
	this.setStyles(this._eraserStyle);
	// 绘制橡皮
	var now = paths[paths.length-1];
	var size = this._eraserStyle['size'];
	var start = {
		x : now.x - size,
		y : now.y - size,
		width: size * 2,
		height: size * 2
	};
	this._context.fillRect(start.x, start.y, start.width, start.height);
	// 清除缓冲层相应的图形
	this._cache.clearRect(start);
	// 还原之前的样式
	this._context.restore();
}
